home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / move15.zip / MOVE.C < prev    next >
C/C++ Source or Header  |  1993-10-05  |  23KB  |  997 lines

  1. /*
  2. Auto:        sc Move NOLINK NODEBUG OPT NOSTARTUP PARM=REGISTER NOSTACKCHECK DATA=NEAR CODE=NEAR STRINGMERGE
  3. Auto:        slink FROM Move.o TO Move LIB LIB:sc.lib LIB:amiga.lib VERBOSE NODEBUG
  4. */
  5.  
  6. /* $Revision Header built automatically *************** (do not edit) ************
  7. **
  8. ** ⌐ Copyright by GuntherSoft
  9. **
  10. ** File             : SnakeSYS:CPrgs/Utils/Move.c
  11. ** Created on       : Wednesday, 11.08.93 15:01:14
  12. ** Created by       : Kai Iske
  13. ** Current revision : V1.5
  14. **
  15. **
  16. ** Purpose
  17. ** -------
  18. **   - Small move utility which supports wildcards and doesn`t use
  19. **     Rename() nor Copy() nor anything similar...
  20. **
  21. ** Revision V1.5
  22. ** --------------
  23. ** created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  24. **  -*-  changed on Tuesday, 05.10.93 02:03:22  by  Kai Iske.   LogMessage :
  25. **   - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment
  26. **     etc. This lead to MungWall hits (of course it did)
  27. **     (Reported by Nico Francois)
  28. **  -*-  created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  29. **   - Exidentially called one ExAll() without ED_SIZE
  30. **     This lead to some calls to DoTheMove without the Size set ;)
  31. **     (Reported by  Karsten Weiss)
  32. **
  33. ** Revision V1.4
  34. ** --------------
  35. ** created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  36. **  -*-  created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  37. **   - Now uses Rename() when source and dest are on the same
  38. **     device. This is faster ;) Why haven`t I thought of that
  39. **     earlier ??? ;)
  40. **
  41. ** Revision V1.3
  42. ** --------------
  43. ** created on Wednesday, 25.08.93 16:32:43  by  Kai Iske.   LogMessage :
  44. **   - UnLock Problem solved when doing recursive Dir-Moves
  45. **     This bug lead to "Object in use" error messages
  46. **
  47. ** Revision V1.2
  48. ** --------------
  49. ** created on Tuesday, 17.08.93 22:48:38  by  Kai Iske.   LogMessage :
  50. **   - Added CTRL-C checking
  51. **   - Added FORCE Flag in order to move read/deleteprotected or
  52. **     to overwrite a delete/writeprotected files
  53. **
  54. ** Revision V1.1
  55. ** --------------
  56. ** created on Monday, 16.08.93 22:53:34  by  Kai Iske.   LogMessage :
  57. **   - Added well known CLONE, DATES, COM, NOPRO,
  58. **     QUIET and NOREQ options also used by e.g. Rename
  59. **
  60. ** Revision V1.0
  61. ** --------------
  62. ** created on Wednesday, 11.08.93 15:01:14  by  Kai Iske.   LogMessage :
  63. **     --- Initial release ---
  64. **
  65. *********************************************************************************/
  66. #define REVISION "1.5"
  67. #define REVDATE  "05.10.93"
  68. #define REVTIME  "02:03:22"
  69. #define AUTHOR   "Kai Iske"
  70. #define VERNUM   1
  71. #define REVNUM   5
  72.  
  73. #include    <string.h>
  74. #include    <stdlib.h>
  75. #include    <exec/types.h>
  76. #include    <proto/exec.h>
  77. #include    <proto/dos.h>
  78. #include    <exec/memory.h>
  79. #include    <exec/execbase.h>
  80. #include    <dos/exall.h>
  81. #include    <dos/dos.h>
  82. #include    <dos/dosextens.h>
  83.  
  84.  
  85.  
  86. /**********************************************************************/
  87. /*                         Defines for Flags                          */
  88. /**********************************************************************/
  89. #define    CLONE        0x0001
  90. #define    DATES        0x0002
  91. #define    NOPRO        0x0004
  92. #define    COM        0x0008
  93. #define    QUIET        0x0010
  94. #define    FORCE        0x0020
  95.  
  96. #define    WATCHSIGS    SIGBREAKF_CTRL_C
  97.  
  98.  
  99.  
  100. /**********************************************************************/
  101. /*                      Static char definitions                       */
  102. /**********************************************************************/
  103. static    char    *Version    = "$VER: Move "REVISION" ("REVDATE")\0";
  104. static    char    *Template    = "FROM/M,TO/A,CLONE/S,DATES/S,NOPRO/S,COM/S,QUIET/S,NOREQ/S,FORCE/S";
  105. enum    {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, LAST_ARG};
  106.  
  107.  
  108.  
  109. /**********************************************************************/
  110. /*                             Prototypes                             */
  111. /**********************************************************************/
  112. int    __saveds DoMove(void);
  113. BOOL    DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask);
  114. BOOL    DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask);
  115.  
  116.  
  117. /**********************************************************************/
  118. /*                          The main program                          */
  119. /**********************************************************************/
  120. int __saveds DoMove(void)
  121. {
  122.     struct    FileInfoBlock    *FIB;
  123.     struct    ExecBase    *SysBase = *((struct ExecBase **)0x4L);
  124.     struct    DOSBase        *DOSBase;
  125.     struct    Process        *MyProc = (struct Process *)SysBase->ThisTask;
  126.     struct    RDArgs        *RDArgs;
  127.     struct    ExAllControl    *EAC;
  128.     struct    ExAllData    *EAB, *EAD;
  129.     APTR    *Args,
  130.         *OldWindow;
  131.     BPTR    DirLock,
  132.         OutHandle;
  133.     char    **FromPtr;
  134.     char    *ToPtr;
  135.     char    Pattern[256];
  136.     char    PathName[256];
  137.     char    Buffer[256];
  138.     LONG    HitMask;
  139.     UWORD    NumFrom = 0, PatternType, CopyFlags = 0;
  140.     BOOL    PatternFrom, GoOn = TRUE, Scanning;
  141.  
  142.         // Ignore startup from WB
  143.  
  144.     if(!(MyProc->pr_CLI))
  145.     {
  146.         struct    Message    *MyMsg;
  147.  
  148.         WaitPort(&MyProc->pr_MsgPort);
  149.         MyMsg = GetMsg(&MyProc->pr_MsgPort);
  150.         Disable();
  151.         ReplyMsg(MyMsg);
  152.         return(0);
  153.     }
  154.  
  155.         // Do the wild thing
  156.  
  157.     if((DOSBase = (struct DOSBase *)OpenLibrary("dos.library", 37)))
  158.     {
  159.         if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  160.         {
  161.                 // Get buffer for ReadArgs()
  162.  
  163.             if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
  164.             {
  165.                     // Get structure for ExAll()
  166.  
  167.                 if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  168.                 {
  169.                         // Get buffer for ExAll()
  170.  
  171.                     if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR)))
  172.                     {
  173.                             // Parse commandline
  174.  
  175.                         if((RDArgs = ReadArgs(Template, (ULONG *)Args, NULL)))
  176.                         {
  177.                                 // From and to really there ??
  178.  
  179.                             if(Args[FROM_ARG] && Args[TO_ARG])
  180.                             {
  181.                                 OutHandle    = Output();
  182.  
  183.                                     // Get Flags
  184.  
  185.                                 if(Args[CLONE_ARG])
  186.                                     CopyFlags    |=    CLONE;
  187.                                 if(Args[DATES_ARG])
  188.                                     CopyFlags    |=    DATES;
  189.                                 if(Args[NOPRO_ARG])
  190.                                     CopyFlags    |=    NOPRO;
  191.                                 if(Args[COM_ARG])
  192.                                     CopyFlags    |=    COM;
  193.                                 if(Args[QUIET_ARG])
  194.                                     CopyFlags    |=    QUIET;
  195.                                 if(Args[FORCE_ARG])
  196.                                     CopyFlags    |=    FORCE;
  197.  
  198.                                     // Check for NOREQ Option
  199.  
  200.                                 if(Args[NOREQ_ARG])
  201.                                 {
  202.                                     OldWindow        = MyProc->pr_WindowPtr;
  203.                                     MyProc->pr_WindowPtr    = (void *)(-1L);
  204.                                 }
  205.  
  206.                                     // Get pointers to Files
  207.  
  208.                                 FromPtr    = (char **)Args[FROM_ARG];
  209.                                 ToPtr    = (char *)Args[TO_ARG];
  210.  
  211.                                     // Count FROM entries
  212.  
  213.                                 while(*FromPtr++)
  214.                                     NumFrom++;
  215.  
  216.                                     // Restore FromPtr
  217.  
  218.                                 FromPtr    = (char **)Args[FROM_ARG];
  219.  
  220.                                     // Set pattern if there are more than 1
  221.                                     // FROM files or if the only FROM file
  222.                                     // is a pattern
  223.  
  224.                                 if(NumFrom > 1)
  225.                                     PatternFrom = TRUE;
  226.                                 else
  227.                                     PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 256);
  228.  
  229.                                     // If a pattern is used, check
  230.                                     // whether the dest really is a dir
  231.  
  232.                                 if(PatternFrom)
  233.                                 {
  234.                                         // Try to obtain a lock
  235.  
  236.                                     if((DirLock = Lock(ToPtr, ACCESS_READ)))
  237.                                     {
  238.                                             // Check file
  239.  
  240.                                         if(Examine(DirLock, FIB))
  241.                                         {
  242.                                                 // Get type of destination entry
  243.  
  244.                                             GoOn = (FIB->fib_DirEntryType > 0);
  245.  
  246.                                                 // If it`s not a directory (multiple files are to be moved)
  247.                                                 // issue an error
  248.  
  249.                                             if(!GoOn)
  250.                                                 FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n");
  251.                                         }
  252.                                         else
  253.                                         {
  254.                                                 // Examine() failed -> Abort
  255.  
  256.                                             GoOn = FALSE;
  257.                                             PrintFault(IoErr(), "\nMove ");
  258.                                         }
  259.  
  260.                                             // Unlock CheckDir
  261.  
  262.                                         UnLock(DirLock);
  263.                                     }
  264.                                     else
  265.                                     {
  266.                                             // If lock failed issue an error
  267.  
  268.                                         PrintFault(IoErr(), "\nMove ");
  269.                                         GoOn = FALSE;
  270.                                     }
  271.                                 }
  272.                                     // Loop for all source files
  273.  
  274.                                 while(NumFrom && GoOn)
  275.                                 {
  276.                                         // Check for CTRL-C
  277.  
  278.                                     if(GoOn)
  279.                                         HitMask    = CheckSignal(WATCHSIGS);
  280.  
  281.                                     if(!HitMask && GoOn)
  282.                                     {
  283.                                             // Check if this source is a pattern
  284.  
  285.                                         strcpy(Buffer, FilePart(*FromPtr));
  286.                                         strupr(Buffer);
  287.                                         PatternType = ParsePatternNoCase(Buffer, Pattern, 256);
  288.  
  289.                                             // It is a pattern
  290.  
  291.                                         if(PatternType == 1)
  292.                                         {
  293.                                                 // Create name of source
  294.  
  295.                                             strcpy(Buffer, *FromPtr);
  296.                                             *PathPart(Buffer)    = '\0';
  297.  
  298.                                                 // Get Lock for Source - Directory
  299.  
  300.                                             if((DirLock = Lock(Buffer, ACCESS_READ)))
  301.                                             {
  302.                                                     // Setup ExAllControl-Structure
  303.  
  304.                                                 EAC->eac_LastKey    = 0L;
  305.                                                 EAC->eac_MatchString    = Pattern;
  306.                                                 EAC->eac_MatchFunc    = NULL;
  307.  
  308.                                                 do
  309.                                                 {
  310.                                                         // Check for CTRL-C
  311.  
  312.                                                     if(GoOn)
  313.                                                         HitMask = CheckSignal(WATCHSIGS);
  314.  
  315.                                                     if(HitMask)
  316.                                                         GoOn = FALSE;
  317.  
  318.                                                         // Scan directory
  319.  
  320.                                                     Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  321.  
  322.                                                         // Issue Error
  323.  
  324.                                                     if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  325.                                                     {
  326.                                                         PrintFault(IoErr(), "\nMove ");
  327.                                                         GoOn = FALSE;
  328.                                                     }
  329.  
  330.                                                         // End of Dir reached
  331.  
  332.                                                     if(EAC->eac_Entries == 0)
  333.                                                         Scanning = FALSE;
  334.                                                     else if(GoOn)
  335.                                                     {
  336.                                                         EAD    = EAB;
  337.  
  338.                                                         do
  339.                                                         {
  340.                                                                 // Check for CTRL-C
  341.  
  342.                                                             if(GoOn)
  343.                                                                 HitMask = CheckSignal(WATCHSIGS);
  344.  
  345.                                                             if(!HitMask && GoOn)
  346.                                                             {
  347.                                                                     // Createfilename for this file to be moved
  348.  
  349.                                                                 strcpy(PathName, *FromPtr);
  350.                                                                 *PathPart(PathName)    = '\0';
  351.                                                                 AddPart(PathName, EAD->ed_Name, 256);
  352.  
  353.                                                                     // Move file
  354.  
  355.                                                                 if((GoOn = DoTheMove(PathName, ToPtr, TRUE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask)) && (EAD->ed_Type > 0))
  356.                                                                 {
  357.                                                                         // Delete directory after a succesful move
  358.  
  359.                                                                     if(!(GoOn = DeleteFile(PathName)))
  360.                                                                         PrintFault(IoErr(), "\nMove ");
  361.                                                                 }
  362.  
  363.                                                                 EAD    = EAD->ed_Next;
  364.                                                             }
  365.                                                             else
  366.                                                                 GoOn = FALSE;
  367.  
  368.                                                         } while(EAD && GoOn);
  369.                                                     }
  370.                                                 } while(Scanning);
  371.  
  372.                                                     // Unlock source directory
  373.  
  374.                                                 UnLock(DirLock);
  375.                                             }
  376.                                             else
  377.                                             {
  378.                                                     // Issue error, if dir could not be locked
  379.  
  380.                                                 PrintFault(IoErr(), "\nMove ");
  381.                                                 GoOn    = FALSE;
  382.                                             }
  383.                                         }
  384.                                             // No pattern
  385.  
  386.                                         else if(PatternType == 0)
  387.                                         {
  388.                                                 // Try to lock source file/dir
  389.  
  390.                                             if((DirLock = Lock(*FromPtr, ACCESS_READ)))
  391.                                             {
  392.                                                     // Examine this lock
  393.  
  394.                                                 if(Examine(DirLock, FIB))
  395.                                                 {
  396.                                                         // Unlock directory and do the move
  397.  
  398.                                                     UnLock(DirLock);
  399.                                                     if((GoOn = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, DOSBase, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask)) && (FIB->fib_DirEntryType > 0))
  400.                                                     {
  401.                                                             // Delete dir after a succesfull move
  402.  
  403.                                                         if(!(GoOn = DeleteFile(*FromPtr)))
  404.                                                             PrintFault(IoErr(), "\nMove ");
  405.                                                     }
  406.                                                 }
  407.                                                 else
  408.                                                 {
  409.                                                         // Issue error on failed Examine()
  410.  
  411.                                                     PrintFault(IoErr(), "\nMove ");
  412.                                                     GoOn = FALSE;
  413.                                                     UnLock(DirLock);
  414.                                                 }
  415.                                             }
  416.                                             else
  417.                                             {
  418.                                                     // No Lock() no more moves
  419.  
  420.                                                 PrintFault(IoErr(), "\nMove ");
  421.                                                 GoOn = FALSE;
  422.                                             }
  423.                                         }
  424.  
  425.                                             // Error condition
  426.  
  427.                                         else
  428.                                         {
  429.                                             PrintFault(IoErr(), "\nMove ");
  430.                                             GoOn = FALSE;
  431.                                         }
  432.  
  433.                                         NumFrom--;
  434.                                         FromPtr++;
  435.                                     }
  436.                                     else
  437.                                         GoOn    = FALSE;
  438.                                 }
  439.                             }
  440.  
  441.                                 // Free ReadArgs
  442.  
  443.                             FreeArgs(RDArgs);
  444.                         }
  445.                         else
  446.                             PrintFault(IoErr(), "\nMove ");
  447.  
  448.                             // Free ExAll-Buffer
  449.  
  450.                         FreeVec(EAB);
  451.                     }
  452.                     else
  453.                         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  454.  
  455.                         // Free ExAllControl Structure
  456.  
  457.                     FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);
  458.                 }
  459.                 else
  460.                     PrintFault(IoErr(), "\nMove ");
  461.  
  462.                     // Free Argument Buffer
  463.  
  464.                 FreeVec(Args);
  465.             }
  466.             else
  467.                 PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  468.  
  469.             FreeVec(FIB);
  470.         }
  471.         else
  472.             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  473.  
  474.             // Check for Abort-Signals
  475.  
  476.         if(HitMask && !(CopyFlags & QUIET))
  477.         {
  478.                 // Display appropriate message
  479.  
  480.             if(HitMask & SIGBREAKF_CTRL_C)
  481.                 FPuts(OutHandle, "\nMove ^C...\n");
  482.         }
  483.  
  484.             // Close DOSLibrary
  485.  
  486.         CloseLibrary((struct Library *)DOSBase);
  487.     }
  488.  
  489.         // Restore old window pointer (if any)
  490.  
  491.     if(OldWindow)
  492.         MyProc->pr_WindowPtr    = OldWindow;
  493.  
  494.  
  495.         // Depending on this flag return appropriate return code
  496.  
  497.     if(GoOn)
  498.         return(0);
  499.     else
  500.         return(10);
  501. }
  502.  
  503.  
  504.  
  505.  
  506. /**********************************************************************/
  507. /*                            Do the move                             */
  508. /**********************************************************************/
  509. BOOL DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask)
  510. {
  511.     struct    ExAllControl    *EAC;
  512.     struct    ExAllData    *EAB, *EAD;
  513.     char    NewDir[256];
  514.     char    Buffer[256];
  515.     UWORD    Len;
  516.     BPTR    DirLock;
  517.     BOOL    RetVal = TRUE, Scanning;
  518.  
  519.         // If a pattern is used print the name of the file to be moved
  520.  
  521.     if(PatternFrom && !(CopyFlags & QUIET))
  522.     {
  523.         strcpy(Buffer, FromFile);
  524.         strcat(Buffer, "...");
  525.         Write(OutHandle, " ", 1);
  526.         Write(OutHandle, Buffer, strlen(Buffer));
  527.     }
  528.  
  529.         // Is it a directory ???
  530.         // If yes, recursively loop for all entries within dir
  531.  
  532.     if(Type > 0)
  533.     {
  534.         strcpy(Buffer, FromFile);
  535.  
  536.             // Get length of from name
  537.  
  538.         Len    = strlen(Buffer);
  539.         if(Len)
  540.         {
  541.             if(Buffer[Len - 1] == '/')
  542.                 Buffer[Len - 1] = '\0';
  543.  
  544.                 // Copy dest name to buffer
  545.  
  546.             strcpy(NewDir, ToPath);
  547.  
  548.                 // Add name of from directory
  549.  
  550.             AddPart(NewDir, FilePart(Buffer), 256);
  551.  
  552.                 // Try to lock directory or
  553.                 // create it, if not existent
  554.  
  555.             if(!(DirLock = Lock(NewDir, ACCESS_READ)))
  556.             {
  557.                 if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET))
  558.                     Write(OutHandle, " [created]...", 13);
  559.             }
  560.  
  561.                 // Got the destination directory ???
  562.  
  563.             if(DirLock)
  564.             {
  565.                     // Unlock Directory
  566.  
  567.                 UnLock(DirLock);
  568.  
  569.                     // Lock sourcedirectory
  570.  
  571.                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  572.                 {
  573.                         // Get ExAll Control for recursive directory search
  574.  
  575.                     if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  576.                     {
  577.                             // Allocate buffer for move
  578.  
  579.                         if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR)))
  580.                         {
  581.                             EAC->eac_LastKey    = 0L;
  582.                             EAC->eac_MatchString    = NULL;
  583.                             EAC->eac_MatchFunc    = NULL;
  584.  
  585.                             do
  586.                             {
  587.                                     // Check for CTRL-C
  588.  
  589.                                 if(RetVal)
  590.                                     (*HitMask) = CheckSignal(WATCHSIGS);
  591.  
  592.                                 if((*HitMask))
  593.                                     RetVal = FALSE;
  594.  
  595.                                     // Scan directory for entries
  596.  
  597.                                 Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  598.  
  599.                                     // Check for an error
  600.  
  601.                                 if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  602.                                 {
  603.                                     PrintFault(IoErr(), "\nMove ");
  604.                                     RetVal = FALSE;
  605.                                 }
  606.  
  607.                                     // End of Dir reached
  608.  
  609.                                 if(EAC->eac_Entries == 0)
  610.                                     Scanning = FALSE;
  611.                                 else if(RetVal)
  612.                                 {
  613.                                     EAD = EAB;
  614.  
  615.                                     do
  616.                                     {
  617.                                             // Check for CTRL-C
  618.  
  619.                                         if(RetVal)
  620.                                             (*HitMask) = CheckSignal(WATCHSIGS);
  621.  
  622.                                         if(!(*HitMask) && RetVal)
  623.                                         {
  624.                                                 // Create filename of source
  625.  
  626.                                             strcpy(Buffer, FromFile);
  627.                                             AddPart(Buffer, EAD->ed_Name, 256);
  628.  
  629.                                                 // And start recursion
  630.  
  631.                                             if((RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask)) && (EAD->ed_Type > 0))
  632.                                             {
  633.                                                     // if file moved was a dir, delete it
  634.  
  635.                                                 if(!(RetVal = DeleteFile(Buffer)))
  636.                                                     PrintFault(IoErr(), "\nMove ");
  637.                                             }
  638.  
  639.                                                 // Loop for all entries
  640.  
  641.                                             EAD = EAD->ed_Next;
  642.                                         }
  643.                                         else
  644.                                             RetVal = FALSE;
  645.  
  646.                                     } while(EAD && RetVal);
  647.                                 }
  648.                             } while(Scanning);
  649.  
  650.                                 // Free ExAll Buffer
  651.  
  652.                             FreeVec(EAB);
  653.                         }
  654.                         else
  655.                         {
  656.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  657.                             RetVal = FALSE;
  658.                         }
  659.  
  660.                             // Free ExAllControl Structure
  661.  
  662.                         FreeDosObject(DOS_EXALLCONTROL, EAC);
  663.                     }
  664.                     else
  665.                     {
  666.                         PrintFault(IoErr(), "\nMove ");
  667.                         RetVal = FALSE;
  668.                     }
  669.  
  670.                     UnLock(DirLock);
  671.                 }
  672.                 else
  673.                 {
  674.                     PrintFault(IoErr(), "\nMove ");
  675.                     RetVal = FALSE;
  676.                 }
  677.             }
  678.             else
  679.             {
  680.                 PrintFault(IoErr(), "\nMove ");
  681.                 RetVal = FALSE;
  682.             }
  683.         }
  684.     }
  685.     else
  686.     {
  687.             // On a plain file -> Simply move it
  688.  
  689.         RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, DOSBase, Size, CopyFlags, HitMask);
  690.     }
  691.  
  692.         // If there was a pattern (or a single directory)
  693.         // end the Move string
  694.  
  695.     if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  696.         FPuts(OutHandle, " moved\n");
  697.  
  698.         // Return Code
  699.  
  700.     return(RetVal);
  701. }
  702.  
  703.  
  704.  
  705.  
  706.  
  707. /**********************************************************************/
  708. /*                      Ein File wirklich moven                       */
  709. /**********************************************************************/
  710. BOOL DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask)
  711. {
  712.     struct    FileInfoBlock    *FIB;
  713.     struct    DevProc        *FromDev, *ToDev;
  714.     BPTR    InFile, OutFile;
  715.     APTR    CopyBuffer;
  716.     char    DestName[256];
  717.     LONG    AvailSize, ReadSize;
  718.     BOOL    RetVal = TRUE, ErrCpy = FALSE, LoopCpy = TRUE, DoRename = FALSE, RemoveFirst = FALSE;
  719.  
  720.     if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  721.     {
  722.  
  723.         strcpy(DestName, ToPath);
  724.  
  725.             // Check, if destfile already exists
  726.             // If so, check if it`s a dir.
  727.             // Yes -> Copy with sourcename
  728.             // No -> Copy with given name
  729.  
  730.         if((OutFile = Lock(DestName, ACCESS_READ)))
  731.         {
  732.             if(Examine(OutFile, FIB))
  733.             {
  734.                     // If dest is a directory move with source name
  735.  
  736.                 if(FIB->fib_DirEntryType > 0)
  737.                     AddPart(DestName, FilePart(FromFile), 256);
  738.                 else
  739.                     RemoveFirst = TRUE;
  740.             }
  741.             else
  742.             {
  743.                     // No examine -> Use source filename
  744.  
  745.                 AddPart(DestName, FilePart(FromFile), 256);
  746.             }
  747.  
  748.             UnLock(OutFile);
  749.         }
  750.  
  751.             // Try to lock input file
  752.  
  753.         if((InFile = Lock(FromFile, ACCESS_READ)))
  754.         {
  755.                 // Get old protection bits, comment and filedate
  756.  
  757.             if(Examine(InFile, FIB))
  758.             {
  759.                     // In Force mode -> Force read and delete permissons
  760.                     // for input file
  761.  
  762.                 if(CopyFlags & FORCE)
  763.                     SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE));
  764.             }
  765.             else
  766.             {
  767.                 PrintFault(IoErr(), "\nMove ");
  768.                 RetVal = FALSE;
  769.             }
  770.  
  771.                 // If so, unlock
  772.  
  773.             UnLock(InFile);
  774.         }
  775.         else
  776.         {
  777.             PrintFault(IoErr(), "\nMove ");
  778.             RetVal = FALSE;
  779.         }
  780.  
  781.  
  782.             // Check whether to use a Rename() or a real Copy-Mode
  783.  
  784.         FromDev    = GetDeviceProc(FromFile, NULL);
  785.         ToDev    = GetDeviceProc(DestName, NULL);
  786.  
  787.             // If the same device is used -> Do the rename
  788.  
  789.         if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
  790.             DoRename = TRUE;
  791.  
  792.         if(FromDev)
  793.             FreeDeviceProc(FromDev);
  794.  
  795.         if(ToDev)
  796.             FreeDeviceProc(ToDev);
  797.  
  798.  
  799.             // No Rename -> Do the right move ;)
  800.  
  801.         if(!DoRename)
  802.         {
  803.                 // Open Input file
  804.  
  805.             if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE)))
  806.             {
  807.                     // Outfile already there ??? and in force mode ???
  808.  
  809.                 if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ))))
  810.                 {
  811.                         // Force delete and write permissons
  812.  
  813.                     UnLock(OutFile);
  814.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  815.                 }
  816.  
  817.                     // Open Output file
  818.  
  819.                 if((OutFile = Open(DestName, MODE_NEWFILE)))
  820.                 {
  821.                         // Get available size of memory
  822.  
  823.                     AvailSize    = AvailMem(MEMF_LARGEST);
  824.                     Size        = (Size > AvailSize) ? AvailSize : Size;
  825.  
  826.                         // Loop till we get a buffer
  827.  
  828.                     while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR)))
  829.                         Size    -= 1024;
  830.  
  831.                     if(CopyBuffer)
  832.                     {
  833.                             // Loop for portions of the source file
  834.  
  835.                         while(RetVal && LoopCpy)
  836.                         {
  837.                                 // Check for CTRL-C
  838.  
  839.                             if(RetVal)
  840.                                 (*HitMask) = CheckSignal(WATCHSIGS);
  841.  
  842.                             if(!(*HitMask) && RetVal)
  843.                             {
  844.                                     // Read part of file
  845.  
  846.                                 if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0)
  847.                                 {
  848.                                         // And write it back
  849.  
  850.                                     if(Write(OutFile, CopyBuffer, ReadSize) == -1)
  851.                                     {
  852.                                         PrintFault(IoErr(), "\nMove ");
  853.                                         RetVal    = FALSE;
  854.                                         ErrCpy    = TRUE;
  855.                                     }
  856.                                 }
  857.                                 else
  858.                                 {
  859.                                         // EOF ??? -> End copy
  860.  
  861.                                     if(ReadSize == 0)
  862.                                         LoopCpy    = FALSE;
  863.                                     else
  864.                                     {
  865.                                             // Otherwise issue error
  866.  
  867.                                         PrintFault(IoErr(), "\nMove ");
  868.                                         RetVal    = FALSE;
  869.                                         ErrCpy    = TRUE;
  870.                                     }
  871.                                 }
  872.                             }
  873.                             else
  874.                                 RetVal = FALSE;
  875.                         }
  876.  
  877.                             // Free Copy buffer
  878.  
  879.                         FreeVec(CopyBuffer);
  880.                     }
  881.                     else
  882.                     {
  883.                             // Issue error
  884.  
  885.                         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  886.                         RetVal    = FALSE;
  887.                         ErrCpy    = TRUE;
  888.                     }
  889.  
  890.                         // Close outfile
  891.  
  892.                     Close(OutFile);
  893.                 }
  894.                 else
  895.                 {
  896.                         // Issue error
  897.  
  898.                     PrintFault(IoErr(), "\nMove ");
  899.                     RetVal = FALSE;
  900.                 }
  901.                     // Close InFile
  902.  
  903.                 Close(InFile);
  904.             }
  905.             else
  906.             {
  907.                     // Issue error
  908.  
  909.                 PrintFault(IoErr(), "\nMove ");
  910.                 RetVal = FALSE;
  911.             }
  912.         }
  913.         else
  914.         {
  915.                 // If RemoveFirst is not set, check again ;)
  916.  
  917.             if(!RemoveFirst)
  918.             {
  919.                 if((OutFile = Lock(DestName, ACCESS_READ)))
  920.                 {
  921.                     if(Examine(OutFile, FIB))
  922.                     {
  923.                         // If dest is a file, delete first
  924.  
  925.                         if(FIB->fib_DirEntryType < 0)
  926.                             RemoveFirst = TRUE;
  927.                     }
  928.                     UnLock(OutFile);
  929.                 }
  930.             }
  931.  
  932.                 // In Rename() mode, the destination has to be removed first
  933.  
  934.             if(RemoveFirst)
  935.             {
  936.                     // If dest file is protected check for FORCE flag
  937.                 if(CopyFlags & FORCE)
  938.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  939.  
  940.                 if(!DeleteFile(DestName))
  941.                 {
  942.                     PrintFault(IoErr(), "\nMove ");
  943.                     RetVal = FALSE;
  944.                 }
  945.             }
  946.  
  947.             if(RetVal)
  948.             {
  949.                     // Now try to "rename" the file
  950.  
  951.                 if(!Rename(FromFile, DestName))
  952.                 {
  953.                     PrintFault(IoErr(), "\nMove ");
  954.                     RetVal = FALSE;
  955.                 }
  956.             }
  957.         }
  958.  
  959.             // Error while copying ?? -> Remove Dest file
  960.  
  961.         if(ErrCpy)
  962.             DeleteFile(DestName);
  963.  
  964.             // No Error -> Remove Source file
  965.  
  966.         if(RetVal && !ErrCpy)
  967.         {
  968.             if(!DoRename && !(RetVal = DeleteFile(FromFile)))
  969.                 PrintFault(IoErr(), "\nMove ");
  970.             else
  971.             {
  972.                     // Set bits etc. as requested
  973.  
  974.                 if((CopyFlags & CLONE) || (CopyFlags & DATES))
  975.                     SetFileDate(DestName, &FIB->fib_Date);
  976.  
  977.                 if((CopyFlags & CLONE) || (CopyFlags & COM))
  978.                     SetComment(DestName, FIB->fib_Comment);
  979.  
  980.                 if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO)))
  981.                     SetProtection(DestName, FIB->fib_Protection);
  982.             }
  983.         }
  984.  
  985.             // Free FileInfo Block
  986.  
  987.         FreeVec(FIB);
  988.     }
  989.     else
  990.     {
  991.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  992.         RetVal = FALSE;
  993.     }
  994.  
  995.     return(RetVal);
  996. }
  997.